package com.yuyou.hxyy.gateway.controller;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.yuyou.hxyy.service.api.bean.LoginRedisObj;
import com.yuyou.hxyy.service.api.bean.PageParams;
import com.yuyou.hxyy.service.api.bean.Pagination;
import com.yuyou.hxyy.service.api.bean.ReturnResult;
import com.yuyou.hxyy.service.api.entity.DataImport;
import com.yuyou.hxyy.service.api.entity.Word;
import com.yuyou.hxyy.service.api.entity.WordUrl;
import com.yuyou.hxyy.service.api.enums.UserEnums;
import com.yuyou.hxyy.service.api.mapper.DataImportMapper;
import com.yuyou.hxyy.service.api.security.SecurityCons;
import com.yuyou.hxyy.service.api.service.*;
import com.yuyou.hxyy.service.api.util.Sequence;
import com.yuyou.hxyy.service.api.util.Webs;
import com.yuyou.hxyy.service.api.vo.req.UserExcel;
import com.yuyou.hxyy.service.api.vo.req.WordExcel;
import com.yuyou.hxyy.service.api.vo.req.WordRepoExcel;
import com.yuyou.hxyy.service.api.vo.req.WordUnitExcel;
import com.yuyou.hxyy.service.api.vo.resp.WordUnitStatisticsVo;
import com.yuyou.hxyy.service.api.vo.resp.WordVo;
import com.yuyou.hxyy.service.api.voice.YoudaoApiUtils;
import io.swagger.annotations.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Api(value="WordController",description="单词接口")
@Validated
@RestController
@RequestMapping(value="/api/word")
public class WordController extends BaseController{

    @Autowired
    private IWordService wordService;

    @Autowired
    private IAuthUserService authUserService;

    @Autowired
    private IWordRepoService wordRepoService;

    @Autowired
    private IWordUnitService wordUnitService;

    @Autowired
    private DataImportMapper dataImportMapper;

    @Autowired
    private IWordUrlService wordUrlService;

    @Autowired
    private IQiniuService qiniuService;

    @ApiOperation(value="获取单词音频")
    @RequestMapping(value ="/getAudio",method = {RequestMethod.GET})
    public void getAudio(@Validated@NotBlank(message = "单词不能为空") @Length(max = 1000 , message = "单词或语句长度不得超过1000个字符")@ApiParam(value = "单词")String word,
                         @Validated@ApiParam(value = "发声：0、女声，1、男声，默认女声" , defaultValue = "0")@RequestParam(value = "per" , required = false)Integer per,
                         @Validated@Range(min = 0,max = 15,message = "只能选择0-15")@ApiParam(value = "语速，取值0-15，默认为5中语速" , defaultValue = "5")@RequestParam(value = "spd" , required = false)Integer spd,
                         @Validated@Range(min = 0,max = 15,message = "只能选择0-15")@ApiParam(value = "音调，取值0-15，默认为5中语调" , defaultValue = "5")@RequestParam(value = "pit" , required = false)Integer pit,
                         @Validated@Range(min = 0,max = 15,message = "只能选择0-15")@ApiParam(value = "音量，取值0-15，默认为5中音量" , defaultValue = "5")@RequestParam(value = "vol" , required = false)Integer vol,
                         HttpServletResponse response) throws IOException {


        //清除所有标点符号
        String cleanedWord = word.replaceAll( "[\\pP+~$`^=|<>～｀＄＾＋＝｜＜＞￥×]" , "").trim();
        WordUrl wordUrl = wordUrlService.findByKey(cleanedWord);

        byte[] b = YoudaoApiUtils.getVoice(cleanedWord , per);
        if(wordUrl == null){//未上传音频的单词

            wordUrl = new WordUrl();
            wordUrl.setCreateTime(new Date());
            wordUrl.setWordUrlId(Sequence.getSequence().nextId());
            wordUrl.setKey(cleanedWord);
            String url = qiniuService.upload(new ByteArrayInputStream(b) , "voice");
            wordUrl.setValue(url);
            wordUrlService.insert(wordUrl);

            wordService.updateByEn(cleanedWord);
        }

        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Content-Disposition",
                "attachment;fileName=1.mp3");
        OutputStream out = response.getOutputStream();
        out.write(b);
        out.flush();
        out.close();
    }

    @ApiOperation(value="获取单词音频")
    @RequestMapping(value ="/dealWordVideo",method = {RequestMethod.POST})
    public ReturnResult<String> dealWordVideo(){
        try {
            wordService.dealWordVideo();
        } catch (Exception e) {
            e.printStackTrace();
            return ReturnResult.fail("同步失败，请联系管理员");
        }
        return ReturnResult.success();
    }


    @ApiOperation("插入单词")
    @PreAuthorize(SecurityCons.admin)
    @RequestMapping(value ="/addWord",method = {RequestMethod.POST})
    public ReturnResult<Void> addWord(@ApiParam(value = "单词")@NotNull(message = "单词不能为空")@RequestParam(value = "en")String en,
                                      @ApiParam(value = "词库ID")@NotNull(message = "词库ID不能为空")@RequestParam(value = "wordRepoId")Long wordRepoId,
                                      @ApiParam(value = "关卡ID")@NotNull(message = "关卡ID不能为空")@RequestParam(value = "wordUnitId")Long wordUnitId,
                                      @ApiParam(value = "音标")@RequestParam(value = "voice" , required = false) String voice,
                                      @ApiParam(value = "语性释义")@RequestParam(value = "cn" , required = false) String cn,
                                      HttpServletRequest request){
        Word wu = wordService.findByRepoUnitEn(wordRepoId , wordUnitId , en);
        if(wu != null){//该关卡已存在该单词
            return ReturnResult.fail("该关卡已存在该单词");
        }
        LoginRedisObj user = this.getUserObj(request);
        wordService.insertWord(en , voice , cn , wordRepoId , wordUnitId , user.getUserId());
        return ReturnResult.success("OK");
    }

    @ApiOperation("更新单词")
    @PreAuthorize(SecurityCons.admin)
    @RequestMapping(value ="/updateWord",method = {RequestMethod.POST})
    public ReturnResult<Void> updateWord(@ApiParam(value = "ID")@NotNull(message = "ID不能为空")@RequestParam(value = "id")Long id,
                                             @ApiParam(value = "单词")@NotNull(message = "单词不能为空")@RequestParam(value = "en")String en,
                                             @ApiParam(value = "音标")@RequestParam(value = "voice",required = false) String voice,
                                             @ApiParam(value = "语性释义")@RequestParam(value = "cn",required = false) String cn,
                                             HttpServletRequest request){
        LoginRedisObj user = this.getUserObj(request);
        wordService.updateWord(id , en , voice ,cn ,user.getUserId());
        return ReturnResult.success("OK");
    }



    @ApiOperation("通过ID获取单词数据")
    @PreAuthorize(SecurityCons.admin)
    @RequestMapping(value ="/getWordById",method = {RequestMethod.GET, RequestMethod.POST})
    public ReturnResult<Word> getWordById(@ApiParam(value = "id")@NotNull(message = "ID不能为空")@RequestParam(value = "id")Long id){
        Word w = wordService.selectByPrimaryKey(id);
        return ReturnResult.success(id);
    }

    @ApiOperation("批量删除单词")
    @PreAuthorize(SecurityCons.admin)
    @RequestMapping(value ="/delWord",method = {RequestMethod.POST})
    public ReturnResult<Void> delWord(@ApiParam(value = "关卡id，多个用逗号隔开")@NotBlank(message = "id不能为空")@RequestParam(value = "ids") String ids){

        wordService.deleteByIds(ids);
        return ReturnResult.success("OK");
    }

    @ApiOperation("单词接口分页查询")
    @RequestMapping(value ="/findWordPage",method = {RequestMethod.GET, RequestMethod.POST})
    public ReturnResult<WordVo> findWordPage(@Validated @ModelAttribute PageParams pageParams,
                                                 @ApiParam(value = "类别")@RequestParam(value = "category" , required = false)Integer category,
                                                 @ApiParam(value = "关卡名称")@RequestParam(value = "en" , required = false) String en,
                                                 @ApiParam(value = "词典ID")@RequestParam(value = "wordRepoId" , required = false) Long wordRepoId,
                                                 @ApiParam(value = "关卡ID")@RequestParam(value = "wordUnitId" , required = false) Long wordUnitId,
                                             HttpServletRequest request){
        Map<String, Object> conditions = new HashMap<>();
        Pagination<WordVo> queryPgn = new Pagination<>();
        queryPgn.setPageParams(pageParams);
        if(category != null){
            conditions.put("category", category);
        }
        if(!StringUtils.isEmpty(en)){
            conditions.put("en", en.trim().replace("%", "\\%").replace("_", "\\_"));
        }
        if(!StringUtils.isEmpty(wordRepoId)){
            conditions.put("wordRepoId", wordRepoId);
        }
        if(!StringUtils.isEmpty(wordUnitId)){
            conditions.put("wordUnitId", wordUnitId);
        }
        queryPgn.setConditions(conditions);
        int total = wordService.findWordCount(queryPgn);
        queryPgn.setTotal(total);
        queryPgn.toBePage();
        if(total > 0){
            List<WordVo> list = wordService.findWordPage(queryPgn);
            queryPgn.setList(list);
        }


        LoginRedisObj user = this.getUserObj(request);
        Map<String, Object> params = new HashMap<>();
        if(!StringUtils.isEmpty(wordUnitId) && user.getUserType() == UserEnums.userType.student.getValue()){
            WordUnitStatisticsVo next = wordUnitService.getStuNextUnitId(wordUnitId , user.getUserId());
            if(next != null){
                params.put("nextId" , next.getId());
                params.put("nextName" , next.getName());
            }
        }
        queryPgn.setExt(params);


        return ReturnResult.success(queryPgn);
    }


    @ApiOperation("导入数据")
    @PreAuthorize(SecurityCons.admin)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "0 用户；1 词库；2 关卡；3 单词", paramType="query",required = true),
            @ApiImplicitParam(name = "file", value = "文件", paramType="query",required = true)
    })

    @RequestMapping(value = "/dataImport", method = {RequestMethod.GET, RequestMethod.POST})
    public ReturnResult<DataImport> dataImport(@NotBlank(message="type不能为空") @RequestParam(value="type") String type,
                                               @RequestParam(value="file") MultipartFile file) throws Exception {

        InputStream inputStream = file.getInputStream();
        ImportParams params = new ImportParams();

        DataImport dataImport = new DataImport();

        if("0".equals(type)){
            List<UserExcel> userExcelList = ExcelImportUtil.importExcel(inputStream, UserExcel.class, params);
            dataImport = authUserService.saveUserImport(userExcelList);

        }
        if("1".equals(type)){
            List<WordRepoExcel> wordRepoExcelList = ExcelImportUtil.importExcel(inputStream, WordRepoExcel.class, params);
            dataImport = wordRepoService.saveWordRepoImport(wordRepoExcelList);
        }
        if("2".equals(type)){
            List<WordUnitExcel> wordUnitExcelList = ExcelImportUtil.importExcel(inputStream, WordUnitExcel.class, params);
            dataImport = wordUnitService.saveWordUnitImport(wordUnitExcelList);

        }
        if("3".equals(type)){
            List<WordExcel> wordExcelList = ExcelImportUtil.importExcel(inputStream, WordExcel.class, params);
            dataImport = wordService.saveWordImport(wordExcelList);
            //生成单词音频，上传到七牛云
            new Thread(() -> {
                try {
                    wordService.dealWordVideo();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }

        return ReturnResult.success(dataImport);
    }

    @ApiOperation("上次导入情况")
    @PreAuthorize(SecurityCons.admin)
    @RequestMapping(value = "/lastInfoImport", method = {RequestMethod.GET,RequestMethod.POST})
    public ReturnResult<DataImport> lastInfoImport(@ApiParam(value = "0 用户；1 词库；2 关卡；3 单词")
                                                   @NotBlank(message="type不能为空") @RequestParam(value="type") String type) {

        DataImport dataImport = dataImportMapper.selectLatestDataImportByType(type);
        return ReturnResult.success(dataImport);
    }

    @ApiOperation("导出失败信息")
    @PreAuthorize(SecurityCons.admin)
    @RequestMapping(value = "/failedInfoExport", method = {RequestMethod.GET,RequestMethod.POST})
    public ReturnResult<Void> failedInfoExport(@ApiParam(value = "0 用户；1 词库；2 关卡；3 单词")
                                               @NotBlank(message="type不能为空") @RequestParam(value="type") String type,
                                               HttpServletRequest request, HttpServletResponse response) {

        DataImport dataImport = dataImportMapper.selectLatestDataImportByType(type);
        XSSFWorkbook excel = new XSSFWorkbook() ;
        if(dataImport != null){
            if("0".equals(type)){
                List<UserExcel> userExcelList = JSONObject.parseObject(dataImport.getContent(), new TypeReference<List<UserExcel>>() {});
                excel = authUserService.failedInfoOfUserImport(userExcelList);

            }
            if("1".equals(type)){
                List<WordRepoExcel> wordRepoExcelList = JSONObject.parseObject(dataImport.getContent(), new TypeReference<List<WordRepoExcel>>() {});
                excel = wordRepoService.failedInfoOfWordRepoImport(wordRepoExcelList);
            }
            if("2".equals(type)){
                List<WordUnitExcel> wordUnitExcelList = JSONObject.parseObject(dataImport.getContent(), new TypeReference<List<WordUnitExcel>>() {});
                excel = wordUnitService.failedInfoOfWordUnitImport(wordUnitExcelList);

            }
            if("3".equals(type)){
                List<WordExcel> wordExcelList = JSONObject.parseObject(dataImport.getContent(), new TypeReference<List<WordExcel>>() {});
                excel = wordService.failedInfoOfWordImport(wordExcelList);
            }
        }

        Webs.writeExcel(request, response, excel , "导入失败信息表");
        return ReturnResult.success("ok");
    }
}
